// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

#ifndef _ADJUSTED_2D_H_
#define _ADJUSTED_2D_H_

#include "options.h"
#include "types.h"

#ifdef __cplusplus
extern "C" {
#endif

/*!
\file
\ingroup	gio
\brief		P-value Adjustment for multiple testing (Epistasis Algorithm)
\details	
	Algorithm based on the PLINK adjustment code for P-values calculations 
	but uses the simpler 'C' data-structures plus extra indexing fields for
	the 2-D epistasis result arrays.
*/

/*! 
\brief Structure containing the %adjusted pvalue statistics (Epistasis Algorithm).
\details 
	Each adjusted_2d structure references a p-value of a SNP pair for a non-permuted epistasis calculation.
*/
struct adjusted_2d {
	/*! \brief Benjamini & Hochberg (1995) step-up FDR control */
	double fdr_bh;

	/*! \brief Bonferroni single-step adjusted p-value */
	double bonf;

	/*! \brief Holm (1979) step-down adjusted p-values */
	double holm;

	/*! \brief P-value */
	double p;

	/*! \brief Epistasis Index */
	int p1;

	/*! \brief Epistasis Index */
	int p2;

	/*! \brief Z-score for the test statistic */
	double z;

	/*! \brief Coefficient Place holder (OR_INT or B_INT) */
	double coeff;
};

/*! 
\brief Create an %adjusted_2d array
\details All numeric elements are initialised to zero.
\param [in] n Size of Array to create
\returns \ref adjusted_2d array or NULL on failure.
*/
struct adjusted_2d* adjusted_2d_create_array(int n);

/*!
\brief Calculate %adjusted pvalues.
\details 
	Make sure that the z scores are bound to the appropriate \ref adjusted_2d::z
	before doing the calculation.<br>

\param [in, out] a The array of %adjusted pvalues.
\param [in] nA Size of the array of %adjusted pvalues.
*/
int adjusted_2d_calc(struct adjusted_2d *a, int nA);

/*! \brief Echo a %adjusted_2d struct to STDOUT. */
void adjusted_2d_echo(struct adjusted_2d *a);

/*! \brief Write a selected list of %adjusted_2d structs to file.
\details
<p>A non-permuted epistasis calculation can generate squillions of %individual interactions.<br>
Only interactions below an significance threshold (e.g. p <= 0.01)
need to be tracked during data-set permutation.<br>
To specify which interactions to keep from the %adjusted_2d array, set the appropriate
boolean flag in the <em>items_to_keep</em> array.</p>

<p>A output file is created locally (see \ref selected_options::ldir) 
and copied to a remote directory (see \ref selected_options::rdir).<br>
The final output filename is a concatonation of selected_options::rdir, selected_options::szRunId
and \ref SUFFIX_PADJ_FILE.
\param [in] a Array of 2-D %adjusted p-values
\param [in] nA Size of the %adjusted p-value array
\param [in] items_to_keep Boolean Array, elements in the 'a' array to write to file
\param [in] ops Input/Output File location
\param [in] rank Rank of processor calling this function
\returns 1 on success, 0 on failure
</p>
*/
int adjusted_2d_write_and_copy(struct adjusted_2d *a, int nA, BOOL *items_to_keep, struct selected_options *ops, int rank);

/*! \brief QSORT Comparator function
\details 
	Compares the epistasis index values (adjusted_2d::p1, adjusted_2d::p2) of 2 adjusted_2d structs
	to see if in same position in a 2-D array.
\param [in] p1 1st Structure
\param [in] p2 2nd Structure
\return 0 if same, -1 if less than, 1 if greater than
*/
int adjusted_2d_cmp(const void* p1, const void* p2);

/*! \brief Load an array of %adjusted_2d structs from a binary file.
\details 
The input file path is a concatonation of selected_options::rdir, selected_options::szRunId
and \ref SUFFIX_PADJ_FILE.
\param [in] ops Location of the input file path
\param [in, out] size Pointer to write the size of the array loaded from file.
\return Array of adjusted_2d or NULL on failure.
*/
struct adjusted_2d* adjusted_2d_load(struct selected_options *ops, int *size);

/*! \brief Find a adjusted_2d struct in a larger array
\details
Function finds a struct in an array by comparing the index values of 
adjusted_2d::p1 and adjusted_2d::p2.<br>
This function uses the binary search algorithm so the contents of the array must 
be sorted.<br>
\param [in] a The array
\param [in] nA Size of the array
\param [in] x Element to find in the array
\returns index of 'x' or -1 if it could not find anything.
*/
int adjusted_2d_search(struct adjusted_2d *a, int nA, struct adjusted_2d *x);

#ifdef __cplusplus
}
#endif

#endif // _ADJUSTED_2D_H_
